#![feature(const_generics)]
#![feature(const_evaluatable_checked)]
#[macro_use]
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn;

#[proc_macro_derive(MemAlloc)]
pub fn derive_mem_alloc_fn(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    // println!("{:?}",&ast);
    
    let name = &ast.ident;
    let generics = &ast.generics;
    let where_clause = &ast.generics.where_clause;
    let gen = quote! {
        impl#generics MemAlloc for #name #generics #where_clause {
            fn new_gtp<P:Sized>(&mut self) -> Result<GTP<P>> {
                (*self.addon.bar).new_gtp::<P>(&mut self.block)
            }
            fn new_gpr<P:Sized>(&mut self) -> Result<(GTP<P>,Raw)> {
                (*self.addon.bar).new_gpr::<P>(&mut self.block)
            }
            fn new<P:Sized>(&mut self) -> Result<UBox<P>> {
                (*self.addon.bar).new::<P>(&mut self.block)
            }
            fn new_gp(&mut self,s :usize) -> Result<GP> {
                (*self.addon.bar).new_gp(&mut self.block,s)
            }
            fn to_raw(&self,s :usize) -> Raw {
                get_mem(&self.block,s)
            }
        }
    };
    gen.into()
}
